package com.horsen.service.user.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.horsen.common.util.ResultCodeEnum;
import com.horsen.service.base.exception.HseduException;
import com.horsen.service.base.model.VO.WebCourseOrderVO;
import com.horsen.service.base.model.VO.WebMemberOrderVO;
import com.horsen.service.base.util.ExceptionUtils;
import com.horsen.service.user.mapper.OrderMapper;
import com.horsen.service.user.model.BO.OrderOutputBO;
import com.horsen.service.user.model.DTO.OrderQueryDTO;
import com.horsen.service.user.model.Order;
import com.horsen.service.user.model.VO.OrderInfoVO;
import com.horsen.service.user.model.VO.OrderListVO;
import com.horsen.service.user.service.MemberService;
import com.horsen.service.user.service.OrderService;
import com.horsen.service.user.service.feign.EduCourseService;
import com.horsen.service.user.utils.OrderNoUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author Horsen
 * @since 2021-05-10
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private EduCourseService eduCourseService;
    @Autowired
    private MemberService memberService;

    /**
     * 根据课程ID新增一个订单
     *
     * @param courseId 课程ID
     * @param memberId 会员ID
     * @return 订单ID
     */
    @Override
    public String insert(String courseId, String memberId) {
        // 查询该会员是否已经购买过该课程
        LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Order::getCourseId, courseId)
                .eq(Order::getMemberId, memberId);
        Order orderExist = baseMapper.selectOne(queryWrapper);
        // 如果订单存在 直接返回订单ID
        if (orderExist != null) {
            return orderExist.getId();
        }
        // 查询课程信息
        WebCourseOrderVO courseOrderVO = eduCourseService.getCourseOrderById(courseId);
        if (courseOrderVO == null) {
            throw new HseduException(ResultCodeEnum.PARAM_ERROR);
        }
        // 查询用户信息
        WebMemberOrderVO memberOrderVO = memberService.getMemberOrder(memberId);
        if (memberOrderVO == null) {
            throw new HseduException(ResultCodeEnum.PARAM_ERROR);
        }
        // 创建一个订单
        Order order = new Order();
        order.setOrderNo(OrderNoUtils.getOrderNo())
                .setCourseId(courseId)
                .setCourseTitle(courseOrderVO.getTitle())
                .setCourseCover(courseOrderVO.getCover())
                .setTeacherId(courseOrderVO.getTeacherId())
                .setTeacherName(courseOrderVO.getTeacherName())
                .setTotalFee(courseOrderVO.getPrice())
                .setMemberId(memberId)
                .setPhone(memberOrderVO.getPhone())
                .setName(memberOrderVO.getName());
        baseMapper.insert(order);
        return order.getId();
    }

    /**
     * 根据ID获取一个订单
     *
     * @param orderId  订单ID
     * @param memberId 会员ID
     * @return 订单信息VO
     */
    @Override
    public OrderInfoVO getById(String orderId, String memberId) {
        LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Order::getId, orderId)
                .eq(Order::getMemberId, memberId);
        OrderInfoVO orderInfoVO = new OrderInfoVO();
        BeanUtils.copyProperties(baseMapper.selectOne(queryWrapper), orderInfoVO);
        return orderInfoVO;
    }

    /**
     * 获取订单支付状态
     *
     * @param courseId 课程ID
     * @param memberId 会员ID
     * @return 是否已经支付
     */
    @Override
    public Boolean isPaid(String courseId, String memberId) {
        LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Order::getMemberId, memberId)
                .eq(Order::getCourseId, courseId)
                .eq(Order::getPaid, 1);
        return baseMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 修改订单支付状态
     *
     * @param orderNo 订单号
     * @return 影响行数
     */
    @Override
    public Boolean pay(String orderNo) {
        try {
            LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Order::getOrderNo, orderNo)
                    .eq(Order::getPaid, 0);
            Order order = baseMapper.selectOne(queryWrapper);
            if (!order.getPaid()) {
                order.setPaid(true);
            }
            boolean result = this.updateById(order);
            if (result) {
                // 修改支付状态成功
                eduCourseService.addBuyCount(order.getCourseId());
            }
            return result;
        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            throw new HseduException(ResultCodeEnum.ORDER_EXIST_ERROR);
        }
    }

    /**
     * 分页查询
     *
     * @param page          当前页码
     * @param limit         每页记录数
     * @param orderQueryDTO 订单查询DTO
     * @return IPage类实例
     */
    @Override
    public IPage<OrderListVO> pageSelect(Long page, Long limit, OrderQueryDTO orderQueryDTO) {
        // 分页参数
        Page<OrderListVO> pageParam = new Page<>(page, limit);
        // 查询结果
        List<OrderListVO> records;
        // 创建条件构造器
        LambdaQueryWrapper<Order> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Order::getDeleted, 0);
        // 设置orderBy关键字
        queryWrapper.orderByDesc(Order::getGmtCreate);
        if (orderQueryDTO != null) {
            String orderNo = orderQueryDTO.getOrderNo();
            String courseTitle = orderQueryDTO.getCourseTitle();
            String teacherName = orderQueryDTO.getTeacherName();
            String name = orderQueryDTO.getName();
            String phone = orderQueryDTO.getPhone();
            Boolean paid = orderQueryDTO.getPaid();
            // 设置查询条件
            if (!StringUtils.isEmpty(orderNo)) {
                queryWrapper.eq(Order::getOrderNo, orderNo);
            }
            if (!StringUtils.isEmpty(courseTitle)) {
                queryWrapper.like(Order::getCourseTitle, courseTitle);
            }
            if (!StringUtils.isEmpty(teacherName)) {
                queryWrapper.like(Order::getTeacherName, teacherName);
            }
            if (!StringUtils.isEmpty(name)) {
                queryWrapper.like(Order::getName, name);
            }
            if (!StringUtils.isEmpty(phone)) {
                queryWrapper.like(Order::getPhone, phone);
            }
            if (paid != null) {
                queryWrapper.eq(Order::getPaid, paid);
            }
        }
        records = baseMapper.selectPage(pageParam, queryWrapper);
        pageParam.setRecords(records);
        return pageParam;

    }

    /**
     * 导出订单到Excel文件
     *
     * @param list 订单列表
     * @return 文件位置
     */
    @Override
    public String output(List<OrderOutputBO> list) {
        String dateTime = new DateTime().toString("yy-MM-dd-HH-mm-ss");
        System.out.println(dateTime);
        String filePath = "E:/Proj_Java/hsedu/excel/order_" + dateTime + ".xlsx";
        EasyExcel.write(filePath, OrderOutputBO.class)
                .sheet("订单信息")
                .doWrite(list);
        return filePath;
    }

    /**
     * 获取销售额
     *
     * @return 销售额
     */
    @Override
    public BigDecimal countPaid() {
        QueryWrapper<Order> queryWrapper = Wrappers.query();
        queryWrapper.select("sum(total_fee) as count").eq("is_paid", 1);
        List<Map<String, Object>> maps = baseMapper.selectMaps(queryWrapper);
        if (maps.get(0) == null) {
            return new BigDecimal(0);
        }
        BigDecimal count = (BigDecimal) maps.get(0).get("count");
        return count;
    }
}
